home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 25
/
Cream of the Crop 25.iso
/
program
/
vgatx10s.zip
/
VGATEXT.DOC
< prev
next >
Wrap
Text File
|
1997-04-12
|
33KB
|
710 lines
zVgaText
============================================================================
Summary Text-mode VGA palette effects class.
Derived None.
Remarks This is a fairly useful class for managing VGA palettes and
screen effect in text mode. This class can handle the general
effect of highlight backgrounds, fade ins and outs, color
pulsing, strobes, gradation, beacons and software simulated
blinking. The functions may look messy at the beginning, but
once you get used to them, you will be amazed at the things
that are possible in text mode. Never let your application
look dull... it implies the programmer was bored with it :-)
Thanks Very big thanks go to Chris Dunford for his ASM code and a
nice text article explaining most of the effects in this class.
He can be contacted at CompuServe, his ID is 76703,2002.
Notes The following are some introductory notes on the text mode
VGA that you might want to know before you look at the class.
These notes combined with the heavy commenting in the source
should enable you to understand the inner workings of the class.
Color mapping
------------------------------------------------------------------------
As programmers who deal with text mode, we are accustomed to using
attributes for specifying the color for the output. It is a nice
and simple relationship (refer to 'conio.h' colors explanation for
textattr() and similar functions). However, the relationship between
this attribute and the actual color displayed on the screen is far
from straight-forward. Before I continue, I should note that the 8
bit color attributes are actually treated as two 4-bit colors. That
is, you have color numbers ranging from 0 to 15 and they can be
either foreground or background.
The color attribute (0-15, the one we use in the programs and the
one that gets stored in the video RAM), is mapped by the VGA BIOS
using an array of 16 registers. It is used as an index into that
array, which in turn selects one of the VGA DAC (Digital-To-Analog)
palettes. These palettes contain the RGB values for each color.
The RGB values are 3 6-bit numbers (18 bits) that can range from
0 to 63 for maximum color saturation.
Basically, the attribute is used as an index into the palette and
the number in the palette is ANDed with the 2 bits in the VGA color
select register to get one of the 256 DAC color definitions. (There
are actually two more ANDings with registers, but since those
usually have all 1's in them, we can safely ignore those steps
completely).
There are a couple of ways to change the color associated with an
attribute: change the attribute itself, change the contents of the
VGA mapping registers, change the contents of the VGA color select
register (2 bits) or change the content of the VGA DAC for the color.
Paging Modes
------------------------------------------------------------------------
The VGA DAC has 256 entries for the colors and each entry has 18
bits (6 per RGB value). Since the maximum number we can use from
the color select register is 2^2 = 4, we can only divide the DAC
into 4 pages of 64 colors each (those 2 bits always end up as the
MSB of the attribute after the mapping in the VGA registers). We
can then select the color with the 6-bit value from the VGA regs.
This is the default mode of the VGA and it is called mode 0.
There is another mode, called mode 1, which combines the data a
bit differently. Instead of only 2 bits from the VGA color select
register, it uses 4, thus enabling us to use 16 palettes with 16
colors each. We will be using this mode because it is a lot more
efficient (we only need to change the VGA color select register
to get to the page) and then we can use the 0-15 attribute to get
to the actual color. No further mapping will be necessary.
Set up
------------------------------------------------------------------------
We can improve the speed of mapping by using a simple setup trick.
We will set the 16 VGA registers to their number, in order, which
will cause them to drop out of the calculations completely. The
0..15 attribute will be combined with the 0..15 page select to get
to the actual DAC color definition. Here's a brief example:
attribute = 3 ; we need to find the color for attr 3
VGA registers[3] = 3 ; because we set them up like that
page select = 4 ; we want to use the color in palette 4
DAC offset = 4*16*3 + 3*3 = 201
Some explanation is in order. First, we decide to find the color
definition (the RGB values) associated with attribute 3. We look
into the VGA palette registers (16 of them) at the position of
the attribute (3). Since we made sure these registers are setup to
contain their index number, this yields 3 as well (we might as well
skip this step altogether). But there are 16 palettes that contain
this particular attribute. We decide to use palette #5 (4, when
indexing from 0, which they are). Each palette has 16 color
definitions, 3 bytes each (for the RGB values). To get to the
offset of the palette, we multiply its index by the size of the
palette (16*3 = 48). To get to the color definition in the palette
itself, we multiply the color by the 3 bytes of RGB definitions and
then simply add the number to the offset. This is the actual offset
into the VGA DAC registers that have the RGB values of the colors.
Techniques
------------------------------------------------------------------------
This class uses a number of techniques for managing the palette
changes that might be useful to know. First, the VGA state is
saved (the palette, the DAC, the paging mode, etc.). Then we
setup our own palette with values 0..15 in it. Then we create
the default color definitions that correspond to the usual ones
set up by the BIOS (and the ones the user will be expecting to
see) in the first palette. Then we copy this palette into all
other 15 palettes. The reason for doing so is simple: since the
BIOS is using mode 0, the VGA registers may contain values that
are larger than 15 (they can go up to 64 actually). When we
switch to mode 1, those values will have their 2 MS bits masked
off and will possibly produce the same new values. We prevent
this by making sure that all registers have valid numbers. Then
the new color definitions are loaded into the VGA DAC registers.
Note that there is a difference between modifying the color
definitions in the class and actually loading them into the VGA.
Even though it is possible to modify a single color definition,
it is often a lot more convenient (and efficient) to load the
entire 16 palettes in one call and thus bring all kinds of changes
into effect immediately.
The VGA text mode effects require that the value of the color
select register be updated continuously. This can be done either
in a routine or in the background. The latter is the approach
adopted by the class. When you call enable(), it will install a
timer tick interrupt handler to manage the content of the register
and thus change palettes in the background, thus creating pulsing,
flashing, and many other effects.
Note that with each effect you create, you 'lose' one of the base
attributes you can use as a normal color. This means that if you
change attribute 4 (red) to be a 'fading cyan', every time you
try to use this attribute, you'll get the fading cyan. You can't
have red in your application unless you redefine another attribute
to be that.
General usage
------------------------------------------------------------------------
Generally, you would use one of the following functions: GradeColor,
SetColor, PulseColor, or BlinkSim to modify the internal DAC user
palette. You would then call disable() (if the timer is currently
running) and then call LoadPalettes() to load the new definitions
into the VGA DAC registers. You can use ResetPalettes() to reset
the colors to their BIOS defaults. When you want to use one of the
effects, you need to call enable() to make sure that the timer
interrupt is running and will be changing the color select register
(thus mapping into a new palette from the DAC). This means that
each tick (or couple of ticks), the routine will change the current
palette (0..15) and the screen will reflect the values for that
color in this palette. This means that setting different values
for the same attribute in different palettes of the DAC and then
simply varying the palette number, the attribute will change its
appearance (in the background). See the demo provided for examples.
ZVGATEXT::ZVGATEXT
------------------------------------------------------------------------
Summary Constructs and initializes the zVgaText object.
Syntax zVgaText();
Remarks The constructor takes care of saving the current VGA DAC
and registers, the paging mode and video page. Note that
the zVgaText object is intended for global usage (i.e.
you cannot have more than one active at any point in your
program), the constructor will abort the application with
an assertion failure if it detects that another zVgaText
object is already created. In essence, this simply calls
resume() to initialize the object.
See also zVgaText::resume
ZVGATEXT::~ZVGATEXT
------------------------------------------------------------------------
Summary Destroys the zVgaText object and restores the VGA state.
Syntax ~zVgaText();
Remarks The destructor simply calls suspend() to restore the state
of the VGA adapter which was saved by resume(). It will
also set the internal running flag to False to indicate
the you can create another zVgaText object if you want to.
This will also restore the blinking if the 'restoreBlink'
flag is set to True.
See also zVgaText::suspend, zVgaText::restoreBlink
ZVGATEXT::DETECT
------------------------------------------------------------------------
Summary Detects the presence of a VGA (or compatible) card.
Syntax static Boolean Detect();
Remarks This routine detects the presence of a VGA (or SVGA) card.
It is mainly intended for use by applications to determine
whether to use the zVgaText object. Since all its member
functions assume that VGA is installed, you might want to
prevent them from running.
Return True if VGA+ card or False otherwise.
ZVGATEXT::RESTOREBLINK
------------------------------------------------------------------------
Summary Flag that tells the suspend() routine to restore blinking.
Syntax static Boolean restoreBlink;
Remarks This publicly accessible flag is modified by EnableBlink()
when you turn off the blinking of characters (thus allowing
all 4 bits for background colors and enabling highlight
backgrounds). You can set it manually to False before
destroying the zVgaText object [or calling suspend()] so
the effect is persistent after program termination.
See also zVgaText::EnableBlink, zVgaText::suspend
ZVGATEXT::RESUME
------------------------------------------------------------------------
Summary Initializes the zVgaText object and saves the VGA state.
Syntax static void resume();
Remarks This is the routine which saves the contents of the VGA
color registers, the paging mode and the DAC RGB values
so that the program can restore them with suspend(). It
will also setup the initial startup mode of the object.
This includes switching to mode 1, setting the VGA registers
to map their indices, creating the default 16 color DAC
definitions in palette 0 and then copying this palette
into the other 15. The net effect will be that the program
will look exactly the same as without the zVgaText object,
but now it is ready to use the text mode effects it has.
Return Nothing.
See also zVgaText::LoadPalettes, zVgaText::suspend
ZVGATEXT::SUSPEND
------------------------------------------------------------------------
Summary Restores the VGA state and suspends the zVgaText object.
Syntax static void suspend();
Remarks This routine will restore the settings saved by resume()
and will activate the original mode and registers. It is
automatically called by the destructor, so you won't need
to call it explicitly. It is useful to call when your
application will be shelling (swapping out of memory) and
you will need to suspend the internal interrupt handler.
This can be done with disable(), but suspend() restores
the VGA to its original state, unlike disable().
Return Nothing.
See also zVgaText::disable, zVgaText::resume
ZVGATEXT::ENABLE
------------------------------------------------------------------------
Summary Enable the interrupt palette switching handler.
Syntax static void enable();
Remarks This routine will install the timer intercept handler which
is used for switching the DAC palettes (enabling the text
mode effects). Note that you need to LoadPalettes() after
you modify them to transfer the new RGB definitions into
the VGA DAC registers. Nothing will happen until you call
enable() to start switching the palettes in the background.
Return Nothing.
See also zVgaText::disable, zVgaText::timerHandler
ZVGATEXT::DISABLE
------------------------------------------------------------------------
Summary Suspends the execution of the timer intercept handler.
Syntax static void disable(char nPalette = 0);
Remarks This removes the timer intercept handler (if one is
installed and sets the current palette number to 'nPalette'.
The effect is that the text mode effect stop working and
the colors 'freeze' to the colors defined in the selected
palette. The usual use would be to leave the default palette
number of 0 to be the palette used. This function will not
do anything if the timer handler is not enabled with a
call to enable() first.
Return Nothing.
See also zVgaText::enable, zVgaText::timerHandler
ZVGATEXT::PULSECOLOR
------------------------------------------------------------------------
Summary Creates a pulsing color over a range of palettes.
Syntax static void PulseColor(char attr, char delta);
static void PulseColor(char attr, char delta,
char start, char end);
Remarks These routines create a pulsing color definition over a
range of palettes. Since the first one simply calls the
second version with 0 and 15 for the 'start' and 'end'
parameters respectively, we will discuss the second one.
A pulsing color is defined as a color definition which
gradually changes its intensity from normal to high and
back to normal. You specify the attribute 'attr' you
need modified (0 to 15), the step value 'delta' and the
'start' (0 to 14) and 'end' (1 to 15) palettes to modify.
The routine will change the RGB color definition for each
of the palettes specified except 'start' itself by making
each palette's color definition values different by 'delta'
from the previous palette. Note that 'end' must be greater
than 'start'. Note that 0-value primaries will not be
modified at all. You will want to call ResetPalettes() to
set the DAC palettes to the same color definitions for
this routine to work. This does not load the modified
palettes into the VGA DAC, use LoadPalettes() to do that.
You also need to call enable() to start the cycling. The
speed and the delta for the cycling are also controllable
with the SetDelay() and SetDelta() member functions. Make
sure you call disable() before you load the DAC registers.
Return Nothing.
See also zVgaText::LoadPalettes, zVgaText::ResetPalettes,
zVgaText::enable, zVgaText::disable, zVgaText::SetDelay
ZVGATEXT::SETCOLOR
------------------------------------------------------------------------
Summary Sets a RGB color definition over a range of palettes.
Syntax static void SetColor(char attr, char rgb[3]);
static void SetColor(char attr, char rgb[3],
char start, char end);
Remarks These routines set the color definition associated with
the attribute 'attr' to the 'rgb' values over a range of
palettes. They don't load the modified palettes into the
VGA DAC registers. Since the first version simply calls
the second with 0 and 15 for the 'start' and 'end' numbers,
we will concentrate on the second function version. You
select the attribute to modify (0 to 15) with the 'attr'
argument and the 3-byte RGB color definition in 'rgb'. Note
that each of the three bytes can contain color intensity
ranging from 0 to 63. The three bytes are the red, green
and blue elements of the definition in that order. The
'start' palette number can be from 0 to 14 and the 'end'
palette - from 1 to 14 (and it must be greater than the
'start' number). This modifies all palettes in the range
specified. To load the modified palettes into the VGA DAC
registers, call LoadPalettes() and then enable() to start
the cycling between them.
Return Nothing.
See also zVgaText::LoadPalettes, zVgaText::enable
ZVGATEXT::GRADECOLOR
------------------------------------------------------------------------
Summary Grades a color definition from one RGB to another.
Syntax static void GradeColor(char attr, char rgb[3]);
static void GradeColor(char attr, char rgb[3],
char start, char end);
Remarks These routines gradually change any RGB color definition
to another over a range of palettes. This allows gradual
changes between two colors. The first version simply calls
the second with 0 and 15 as the 'start' and 'end' values.
You select the attribute to modify with the 'attr' argument
and the starting and ending palettes with the 'start' and
'end' parameters. The function will use the RGB definition
for the attribute in the starting palette and calculate
the scaling factors to change it into the 'rgb' definition
requested over the range of palettes between 'start' and
'end'. The RGB definition specifies the red, green and
blue color saturations which can range from 0 to 63 each.
The attribute should be between 0 and 15, the 'start'
palette - from 0 to 14 and the 'end' - from 1 to 15, with
'end' larger than 'start'. The RGB definition in the
'start' palette is not modified. The new palettes are not
loaded into the VGA DAC (use LoadPalettes() for that). You
must call enable() to start cycling the palettes.
Return Nothing.
See also zVgaText::LoadPalettes, zVgaText::CalcScale
ZVGATEXT::BLINKSIM
------------------------------------------------------------------------
Summary Simulates blinking in software.
Syntax static void BlinkSim(char attr);
Remarks This routine simulates blinking in software. Unlike all
other routines which use 4-bit attributes, this one uses
the full 8 bits in the normal foreground/background
format (LSB - FG and MSB - BG). It simply modifies the
palettes 8-15 for the foreground attribute and puts the
RGB values from palette 0 for the background attribute.
Since the foreground attribute's palettes 0-7 are not
modified, you can use all the special effects provided
in that range. This will give you a blinking special
effect. How about that? This routine does not load the
modified palettes into the VGA DAC registers. You can
use LoadPalettes() to do that. You must call enable()
to start the actual palette cycling.
Return Nothing.
See also zVgaText::enable, zVgaText::LoadPalettes
ZVGATEXT::FADEOUT
------------------------------------------------------------------------
Summary Fades out (to black) all attributes over the 16 palettes.
Syntax static void FadeOut(char aDelay = 12);
Remarks This routine fades out all colors to black and returns.
Unlike most other routines, this one actually modifies
the VGA DAC and performs the operation before returning.
The default delay of 12 milliseconds between steps is
usually enough, but you can change it to taylor the speed
of the effect (higher values result in slower fading). The
routine will modify the VGA DAC registers and you may want
to call ResetPalettes() when it is done. Also note that
you MUST disable() the timer intercept handler before
calling this routine. This function is great for program
exits when you would fade out the screen before returning
to the command prompt.
Return Nothing.
See also zVgaText::ResetPalettes, zVgaText::disable
ZVGATEXT::FADEIN
------------------------------------------------------------------------
Summary Fades in default colors from black.
Syntax static void FadeIn(char aDelay = 12);
Remarks This routine is the opposite of FadeOut() in that it
gradually fades in the colors from black to the original
(default) attributes. Unlike most other routines, this
one does all palette handling and does modify the VGA
DAC registers. You MUST call disable() before using this
routine to suspend the timer intercept handler. You may
also want to use ResetPalettes() after using this function
to set the 16 palettes to their default values. This
effect is great for program startup where you would fade
in the screen of your program instead of simply popping
the main application window. It looks more professional.
The default delay between the fading steps is set to 12
milliseconds and in most cases it is sufficient. You can
use different values (greater numbers slow down the effect).
Return Nothing.
See also zVgaText::disable, zVgaText::ResetPalettes
ZVGATEXT::RESETPALETTES
------------------------------------------------------------------------
Summary Sets the 16 palettes to the default color RGB values.
Syntax static void ResetPalettes();
Remarks Use this routine to re-initialize the 16 palettes to
the default colors used by the VGA BIOS. This will create
color definitions with RGB entries that look almost like
the defaults. The reason I say 'almost', is because the
bright colors will appear dimmer. This is done on purpose
because it will give you some room to vary the intensity
of those attributes too. This routine resets the internal
DAC buffer but does not load the new palettes into the
VGA itself. you need to call LoadPalettes() to do that.
Usually, you will want to reset the palettes in order to
put the color definitions in some predictable known state.
Resetting the palettes also sets the current palette to 0.
Return Nothing.
See also zVgaText::LoadPalettes
ZVGATEXT::LOADPALETTES
------------------------------------------------------------------------
Summary Loads the internal palettes into the VGA DAC registers.
Syntax static void LoadPalettes();
Remarks This is one of the most important functions you will be
using. Whenever you use the member functions to modify
the internal palettes (GradeColor, SetColor, PulseColor
or BlinkSim), nothing will happen without calling this
routine first. This function will reload all 256 color
definitions into the VGA DAC registers. Of course, it is
possible to modify the contents one by one on a per-need
basis, except this is more efficient and lets you modify
a lot of definitions in one shot. Before you call this
routine, you MUST call disable() to suspend the timer
intercept handler if you have one installed. This is to
prevent the interrupt from occurring while the BIOS is
loading the DAC with the definitions. It won't really
hurt much except the display will probably be messed up
for an instant. It's just good style. Note that even
loading the palettes will not cause the effects to work
until you call enable() to install the background handler.
Return Nothing.
See also zVgaText::enable, zVgaText::disable
ZVGATEXT::ENABLEBLINK
------------------------------------------------------------------------
Summary Enables or disables the blinking attribute.
Syntax static void EnableBlink(Boolean enable);
Remarks This routine changes the interpretation of the blink bit
(the MSB of the attribute). The normal VGA operation is
to make the characters blink if this bit is on, thus
leaving only 3 bits for a maximum of 8 background colors.
If you disable the blinking, you get the 4 bits for a
maximum of 16 background colors (which enables you to use
bright backgrounds). Since you can easily simulate the
blinking with the BlinkSim() function, you might want to
do that anyway. Note that resume() will not automatically
set this for you, it is up to the programmer. However,
calling EnableBlink(True) (which enables the blinking)
will set the internal 'restoreBlink' flag to False and
EnableBlink(False) which enables the bright backgrounds
will set the flag to True. This flag is used by suspend()
to see if the mode needs restoring. Since this is what
you usually want, you can leave it like that. However,
the 'restoreBlink' flag is publicly accessible. This is
done so you can set it manually to False after enabling
bright backgrounds in the rare case where you might want
to preserve the setting after the object has been destroyed
(like after program termination, for example).
Return Nothing.
See also zVgaText::restoreBlink, zVgaText::suspend
ZVGATEXT::SETDELAY
------------------------------------------------------------------------
Summary Sets the delay between the palette switching.
Syntax static void SetDelay(ushort nTicks);
Remarks This sets the number of ticks that must be skipped before
a palette switch occurs in the timer intercept handler (if
one is installed and running). The default setting is 1.
Higher settings will make the effects slower.
Return Nothing.
See also zVgaText::setDelta, zVgaText::timerHandler
ZVGATEXT::SETDELTA
------------------------------------------------------------------------
Summary Sets the palette delta increment.
Syntax static void SetDelta(char delta);
Remarks This sets the palette increment for each step. Whenever
a timer palette switch occurs (after the number of ticks
defined by SetDelay), the current palette will be changed
by that many palettes. The 'delta' value is checked and
made a multiple of the current palette number (to ensure
proper operation). This can be a negative number, but
the timer handler usually controls the direction itself.
The default value is 1 which makes palettes increment and
decrement in succession. You can set higher values if you
want to skip over palettes (and make the changes more
abrupt than gradual). This will set the internal value
even if the timer handler is not installed.
Return Nothing.
See also zVgaText::SetDelay, zVgaText::timerHandler
ZVGATEXT::GETDACPTR
------------------------------------------------------------------------
Summary Get a pointer to the RGB color definition.
Syntax static uchar* GetDacPtr(char attr, char palette);
Remarks This routine retrieves a pointer to the RGB color definition
associated with the attribute 'attr' in the 'palette'
palette. This is a protected member and can be only used
in derived classes. This takes into consideration the VGA
mapping registers and will force correct values for both
arguments. The pointer returned can be used to set the
RGB values for the attribute in the palette (red, green
and blue, in that order). Using the pointer to modify the
values will actually affect the internal buffer which will
not be loaded into the VGA DAC registers until LoadPalette.
Return Pointer to the RGB definition in palette for attribute.
ZVGATEXT::CALCSCALE
------------------------------------------------------------------------
Summary Calculates the color gradation scale parameters.
Syntax static void CalcScale(char rgbStart[3], char rgbEnd[3],
char nRange);
Remarks This protected member function calculates the scaling
factor required to change the RGB definition in the
'rgbStart' parameter to the one in 'rgbEnd' over a
range of 'nRange' palettes. The scale is very simple:
it consists of an increment value, a fixup and a fixup
range. The increment value (positive or negative) is
the number that will be added to the starting definition
during each step. The fixup range is the number of steps
where the fixup value will be added too. The fixup value
will always be either 1 or -1 and is used to compensate
for the possible difference after adding all the increments
(distributed over the fixup range, which will always be
between 0 and 14). This routine works in both directions:
it will scale colors either up or down, and will treat
all three values (RGB) independently. That is, it creates
three different scaling factors (one for each of them).
Return Nothing.
See also zVgaText::GradeColor
ZVGATEXT::TIMERHANDLER
------------------------------------------------------------------------
Summary The actual palette switching timer intercept handler.
Syntax static void interrupt timerHandler(...);
Remarks Even though this is a private member, it is documented
here to show the mechanism which accomplishes the effect
of switching the palettes. On each timer tick, the
'countdown' value is decremented. When it reaches 0, it
is reset to the value given by SetDelay(). Then the
current palette number (always between 0 and 15) is
incremented by 'delta' (see the SetDelta() routine). The
new value is then checked for validity (i.e. we make sure
it's between 0 and 15 again). If we are out of range, we
adjust the value and reverse the direction of the increment
by negating 'delta'. Then the VGA is instructed to use
the new palette (DAC page with 16 color definitions) to
display the colors associated with the attributes. It will
then chain the old timer handler to give other routines
a chance to execute too.
Return Nothing.
See also zVgaText::SetDelay, zVgaText::SetDelta